Skip to content

Conversation

felix642
Copy link
Contributor

@felix642 felix642 commented Oct 6, 2025

This is another attempt at fixing #108455. Please see the initial discussion in the following PR: #111453

This parameter is used to suppress the Unknown argument '...' error that clang will emit whenever it encounters an unknown argument.

This is probably an error to make sure the user fixes it's mistake by either removing the argument or renaming it, but there are some cases where it's not possible to fix the issue.
For instance, CMake now injects gcc-specific arguments in the clang-tidy command that breaks static-analysis
(https://gitlab.kitware.com/cmake/cmake/-/issues/26283)

This will also allow users to run clang-tidy / clangd on a gcc-based project without the need to maintain two separate build commands to run llvm-based tools.

By enabling this parameter, the user is able to downgrade the error to a warning (unknown-argument) that he can further silence using the -Qunused-arguments flag if needed.

Fixes: #108455

This parameter is used to suppress the ``Unknown argument '...'`` error
that clang will emit whenever it encounters an unknown argument.

This is probably an error to make sure the user fixes it's mistake by
either removing the argument or renaming it, but there are some cases
where it's not possible to fix the issue.
For instance, CMake now injects gcc-specific arguments in the clang-tidy
command that breaks static-analysis
(https://gitlab.kitware.com/cmake/cmake/-/issues/26283)

This will also allow users to run clang-tidy / clangd on a
gcc-based project without the need to maintain two separate
build commands to run llvm-based tools.

By enabling this parameter, the user is able to downgrade the error to a
warning (unknown-argument) that he can further silence using the
``-Qunused-arguments`` flag if needed.

Fixes: llvm#108455
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Oct 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 6, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-driver

Author: Félix-Antoine Constantin (felix642)

Changes

This is another attempt at fixing #108455. Please see the initial discussion in the following PR: #111453

This parameter is used to suppress the Unknown argument '...' error that clang will emit whenever it encounters an unknown argument.

This is probably an error to make sure the user fixes it's mistake by either removing the argument or renaming it, but there are some cases where it's not possible to fix the issue.
For instance, CMake now injects gcc-specific arguments in the clang-tidy command that breaks static-analysis
(https://gitlab.kitware.com/cmake/cmake/-/issues/26283)

This will also allow users to run clang-tidy / clangd on a gcc-based project without the need to maintain two separate build commands to run llvm-based tools.

By enabling this parameter, the user is able to downgrade the error to a warning (unknown-argument) that he can further silence using the -Qunused-arguments flag if needed.

Fixes: #108455


Full diff: https://github.com/llvm/llvm-project/pull/162201.diff

4 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+3)
  • (modified) clang/lib/Driver/Driver.cpp (+22-20)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (+11-9)
  • (modified) clang/test/Driver/unsupported-option.c (+4)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 2ef609831637e..de0d32f68253a 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1011,6 +1011,9 @@ def : Flag<["-"], "Xcompiler">, IgnoredGCCCompat;
 def Z_Flag : Flag<["-"], "Z">, Group<Link_Group>;
 def all__load : Flag<["-"], "all_load">;
 def allowable__client : Separate<["-"], "allowable_client">;
+def allow_unrecognized_arguments : Flag<["--"], "allow-unrecognized-arguments">,
+    Visibility<[ClangOption, CLOption]>,
+    HelpText<"Ignore unrecognized command-line arguments instead of reporting an error.">;
 def ansi : Flag<["-", "--"], "ansi">, Group<CompileOnly_Group>;
 def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">;
 def arch : Separate<["-"], "arch">, Flags<[NoXarchOption,TargetSpecific]>;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 85a1335785542..4f2ac9ba8271c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -303,29 +303,31 @@ InputArgList Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings,
     }
   }
 
-  for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) {
-    unsigned DiagID;
-    auto ArgString = A->getAsString(Args);
-    std::string Nearest;
-    if (getOpts().findNearest(ArgString, Nearest, VisibilityMask) > 1) {
-      if (!IsCLMode() &&
-          getOpts().findExact(ArgString, Nearest,
-                              llvm::opt::Visibility(options::CC1Option))) {
-        DiagID = diag::err_drv_unknown_argument_with_suggestion;
-        Diags.Report(DiagID) << ArgString << "-Xclang " + Nearest;
+  if (!Args.hasArg(options::OPT_allow_unrecognized_arguments)) {
+    for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) {
+      unsigned DiagID;
+      auto ArgString = A->getAsString(Args);
+      std::string Nearest;
+      if (getOpts().findNearest(ArgString, Nearest, VisibilityMask) > 1) {
+        if (!IsCLMode() &&
+            getOpts().findExact(ArgString, Nearest,
+                                llvm::opt::Visibility(options::CC1Option))) {
+          DiagID = diag::err_drv_unknown_argument_with_suggestion;
+          Diags.Report(DiagID) << ArgString << "-Xclang " + Nearest;
+        } else {
+          DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl
+                              : diag::err_drv_unknown_argument;
+          Diags.Report(DiagID) << ArgString;
+        }
       } else {
-        DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl
-                            : diag::err_drv_unknown_argument;
-        Diags.Report(DiagID) << ArgString;
+        DiagID = IsCLMode()
+                     ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion
+                     : diag::err_drv_unknown_argument_with_suggestion;
+        Diags.Report(DiagID) << ArgString << Nearest;
       }
-    } else {
-      DiagID = IsCLMode()
-                   ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion
-                   : diag::err_drv_unknown_argument_with_suggestion;
-      Diags.Report(DiagID) << ArgString << Nearest;
+      ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) >
+                       DiagnosticsEngine::Warning;
     }
-    ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) >
-                     DiagnosticsEngine::Warning;
   }
 
   for (const Arg *A : Args.filtered(options::OPT_o)) {
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 422375240bab6..0ba29db471617 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4991,15 +4991,17 @@ bool CompilerInvocation::CreateFromArgsImpl(
     Diags.Report(diag::err_drv_missing_argument)
         << Args.getArgString(MissingArgIndex) << MissingArgCount;
 
-  // Issue errors on unknown arguments.
-  for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
-    auto ArgString = A->getAsString(Args);
-    std::string Nearest;
-    if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1)
-      Diags.Report(diag::err_drv_unknown_argument) << ArgString;
-    else
-      Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
-          << ArgString << Nearest;
+  if (!Args.hasArg(options::OPT_allow_unrecognized_arguments)) {
+    // Issue errors on unknown arguments.
+    for (const auto *A : Args.filtered(OPT_UNKNOWN)) {
+      auto ArgString = A->getAsString(Args);
+      std::string Nearest;
+      if (Opts.findNearest(ArgString, Nearest, VisibilityMask) > 1)
+        Diags.Report(diag::err_drv_unknown_argument) << ArgString;
+      else
+        Diags.Report(diag::err_drv_unknown_argument_with_suggestion)
+            << ArgString << Nearest;
+    }
   }
 
   ParseFileSystemArgs(Res.getFileSystemOpts(), Args, Diags);
diff --git a/clang/test/Driver/unsupported-option.c b/clang/test/Driver/unsupported-option.c
index 7234e52571582..465f1879b31c8 100644
--- a/clang/test/Driver/unsupported-option.c
+++ b/clang/test/Driver/unsupported-option.c
@@ -32,3 +32,7 @@
 // RUN: not %clang -c -Qunused-arguments --target=aarch64-- -mfpu=crypto-neon-fp-armv8 %s 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=QUNUSED_ARGUMENTS
 // QUNUSED_ARGUMENTS: error: unsupported option '-mfpu=' for target 'aarch64--'
+
+// RUN: %clang %s -invalid --allow-unrecognized-arguments -### 2>&1 | \
+// RUN: FileCheck %s --check-prefix=UNKNOWN_ARGUMENT
+// UNKNOWN_ARGUMENT: warning: argument unused during compilation: '-invalid'

@felix642
Copy link
Contributor Author

felix642 commented Oct 6, 2025

@nicovank @carlosgalvezp @AaronBallman @HerrCai0907 @5chmidti @MaskRay
You were part of the initial PR ( #111453 ) and added comments regarding the initial implementation.
If you have any comments regarding this new patch I would love to hear it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ignore unknown flags in clang-tidy
2 participants